#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>

#define STOP 0
#define PAUSE 1
#define CONTI 2
#define PLAY 3
#define TOP 4
#define NEXT 5
#define ADD 6
#define DETETE 7
#define READ  8
#define RIGHT 9
#define LEFT 10
#define VOLUME 11
#define NC 12
#define COM_NUM 13

static struct class *player_class;
static struct device *player_device;

static int id=0;
static int com=NC;
static char com_id_w=0;
static char com_id_r=0;
static int balabce=50;
static int volume=50;

static int player_open(struct inode *inode, struct file *file) {
	//url = kmalloc(100,sizeof(char));
	return 0;
}

#define COMMAND 0
#define ID 1
#define BALANCE 2
#define WRITE_ID 255
#define READ_ID 254
#define WRITE_BAL 245
#define READ_BAL 244
long player_ioctl(struct file *file, unsigned int com_id, unsigned long data){
	switch(com_id){
		case READ_ID:com_id_r = ID;break;
		case WRITE_ID:com_id_w = ID;break;
		case:WRITE_BAL:com_id_r = BALANCE;break;
    case:READ_BAL:com_id_w = BALANCE;break;
			}
	return 0;
}

ssize_t player_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	if(com_id_w == COMMAND){
		copy_from_user(&com,buf,4);
		printk("mod_write:id = %d\n", id);
	}else if(com_id_w == ID){
		copy_from_user(&id,buf,4);
		com = PLAY;
		printk("mod_write:id = %d\n", id);
		com_id_w = COMMAND;
	}else if(com_id_w == BALANCE){
		copy_from_user(&id,buf,4);
		if(id){
			com = LEFT;
			if(balance>0){

			}
		}else{
			com = RIGHT;
			if(balance <100){
				
			}
		}		
		printk("mod_write:id = %d\n", id);
		com_id_w = COMMAND;
	}
	return 0;
}

ssize_t player_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	if(com_id_r == COMMAND){
		copy_to_user(buf, &com, 4);
	  printk("mod_write:com = %d\n", com);
	}
	else if(com_id_r == ID){
	 copy_to_user(buf, &id, 4);
	 printk("mod_write:id = %d\n", id);
	 com_id_r = COMMAND;
	}
	else if(com_id_r == BALANCE){
	 copy_to_user(buf, &id, 4);
	 printk("mod_write:id = %d\n", id);
	 com_id_r = COMMAND;
	}
	return sizeof(id);
}

static struct file_operations player_fops={
	.owner = THIS_MODULE,
	.read = player_read,
	.write = player_write,
	.unlocked_ioctl = player_ioctl,
	.open = player_open,
};

int major;
static int player_init(void){
	major = register_chrdev(0,"player_dev",&player_fops);
	player_class = class_create(THIS_MODULE, "player_dev");
	player_device = device_create(player_class, NULL, MKDEV(major, 0), NULL, "KTV");
	return 0;
}

static void player_exit(void){
	unregister_chrdev(major, "player_dev");
	device_unregister(player_device);
	id = 0;
	class_destroy(player_class);
}

module_init(player_init);
module_exit(player_exit);

MODULE_LICENSE("GPL");
